﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Configuration;

using System.Threading;

using System.Data.SqlClient;

using crmbl.Azure.Globals;
using crmbl.Azure.Metadata.Globals;
using crmbl.Azure.Diagnostics.EventLogs.Processor;
using crmbl.Azure.Diagnostics.Logs.Processor;
using crmbl.Azure.Diagnostics.PerformanceCounters.Processor;

namespace AzureDiagnosticsProcessor
{
    public partial class WADProcessor : ServiceBase
    {
        public WADProcessor()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork));
        }

        protected void DoWork(object objectState)
        {
            // This needs to be made into an async parallel processing application
            try
            {
                int downloadExecutions = 1;

                Logger.WriteMessage("WADProcessor Service has started.", EventLevel.Information, 2001);

                // Infinate Service Loop
                while (1 == 1)
                {
                    try
                    {
                        // Start the loop 
                        String localDatabaseConnectionString = ConfigurationManager.ConnectionStrings["ApplicationDiagnosticsDatabase"].ConnectionString;

                        using (ApplicationHelper app = new ApplicationHelper(localDatabaseConnectionString))
                        {
                            foreach (StorageAccount storageAccount in app.GetStorageAccounts())
                            {
                                /* WAD Log Processor*/
                                try
                                {
                                    using (LogsProcessor logProcessor = new LogsProcessor(storageAccount.StorageAccountId, storageAccount.StorageAccountName, storageAccount.StorageAccountKey, localDatabaseConnectionString))
                                    {
                                        logProcessor.Process();
                                    }
                                }
                                catch (Exception ex)
                                {
                                    Logger.WriteMessage(String.Format("Unhandled exception when processing ETW logs for the storage account {0}.  EXCEPTION: {1}", storageAccount.StorageAccountName, ex.ToString()), EventLevel.Warning, 2106);
                                }

                                /* Event Logs*/
                                try
                                {
                                    using (EventLogProcessor evtProcessor = new EventLogProcessor(storageAccount.StorageAccountId, storageAccount.StorageAccountName, storageAccount.StorageAccountKey, localDatabaseConnectionString))
                                    {
                                        evtProcessor.Process();
                                    }
                                }
                                catch (Exception ex)
                                {
                                    Logger.WriteMessage(String.Format("Unhandled exception when processing Windows Event logs for the storage account {0}.  EXCEPTION: {1}", storageAccount.StorageAccountName, ex.ToString()), EventLevel.Warning, 2107);
                                }

                                /* Performance Counters*/
                                try
                                {
                                    using (PerformanceCounterProcessor perfProcessor = new PerformanceCounterProcessor(storageAccount.StorageAccountId, storageAccount.StorageAccountName, storageAccount.StorageAccountKey, localDatabaseConnectionString))
                                    {
                                        perfProcessor.Process();
                                    }
                                }
                                catch (Exception ex)
                                {
                                    Logger.WriteMessage(String.Format("Unhandled exception when processing Performance Counters for the storage account {0}.  EXCEPTION: {1}", storageAccount.StorageAccountName, ex.ToString()), EventLevel.Warning, 2107);
                                }

                                try
                                {
                                    int aggregationInterval = 100;

                                    try
                                    {
                                        aggregationInterval = int.Parse(ConfigurationManager.AppSettings["PerformanceAggregationRunIntervals"]);
                                    }
                                    catch (Exception) { }

                                    if ((downloadExecutions % aggregationInterval) == 0)
                                    {
                                        app.RunDataAggregations();
                                    }
                                }
                                catch (Exception ex)
                                {

                                }
                            }
                        }
                    }
                    catch (SqlException sqlEx)
                    {
                        Logger.WriteMessage(String.Format("SQL Connection failure in WADProcessor Service loop.  The service will continue to run at next loop interval.  EXCEPTION: {0}", sqlEx.ToString()), EventLevel.Error, 2664);
                    }
                    catch (Exception ex)
                    {
                        Logger.WriteMessage(String.Format("Unhandled exception caught in the WADProcessor Service loop.  The service will continue to run.  EXCEPTION: {0}", ex.ToString()), EventLevel.Warning, 2665);
                    }

                    int sleepIntervalMS = 300000;
                    try
                    {
                        sleepIntervalMS = int.Parse(ConfigurationManager.AppSettings["ServiceLoopWaitIntervalMS"]);
                    }
                    catch (Exception ex)
                    {
                        Logger.WriteMessage(String.Format("Failed to convert configuration value for 'ServiceLoopWaitIntervalMS' to int, default value of {0} will be used. EXCEPTION: {1}", sleepIntervalMS, ex.ToString()), EventLevel.Warning, 2016);
                    }

                    downloadExecutions++;

                    System.Threading.Thread.Sleep(sleepIntervalMS);


                }

            }
            catch (Exception ex)
            {
                Logger.WriteMessage(String.Format("Unhandled exception in the WADProcessor Service.  The service will be a faulted state. EXCEPTION: {0} ", ex.ToString()), EventLevel.Error, 2666);
            }
        }

        protected override void OnStop()
        {
            Logger.WriteMessage("WADProcessor Service is stopping.", EventLevel.Information, 2999);
        }
    }
}
